/*
@STI LICENSE
(C) 2006-2008 Universit�t Innsbruck.

This file is part of myOntology.

myOntologyis free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

myOntologyis distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with myOntology.  If not, see <http://www.gnu.org/licenses/>.

@STI LICENSE */
package controller;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import model.ActionOnElement;
import model.DHTMLConstants;
import model.RankedElement;
import model.Vocabulary;
import model.dataContainer.TranslationContainer;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;

import view.HTMLUIcomponents.AbstractComponent;
import controller.elementMapper.Mapper;
import controller.sesameDataConnector.AbstractDataConnector;

public class HelperFunctions {


	public static Logger logger = Logger.getLogger(HelperFunctions.class);
	
	public static final String SYNONYMSPLITTER = " ";
	public static final String TAGSSPLITTER = " ";
	public static final String DEFAULTPLITTER = ",";
	public static final String INNERTRANSLATIONSPLITTER = ";"; // splits value from language (e.g. "bla; de")
	
	public static final int MAXPARALLELTREENODES = 7;  //number of maximum parallel nodes in tree view
	public static final int MAXPARALLELTREENODESTOLERANCE = 3; //if only a few more concepts on a level, also show them
	public static final String MORECONCEPTSOBJECTID = "__MORECONCEPTSOBJECTID__";
	public static final String SUPERCONCEPTIDENTIFIER = "__SUPERCONCEPT__";
	public static final int MAXONTMODULESFORTREE = 10;	
	private static final String YOUTUBEDEVID = "jpZw5IQr-HI";
	
	/**
	 * Generates HTML Code with a link in it to create a new element.
	 * @param formAction	The action of the form (Target where the form should be sent to)
	 * @param formName		The name of the form (to differentiate between other forms)
	 * @param action		The action of the link. This is requested afterwards by request.getParameter( "action" )
	 * @param label			The linked label of the fastLink
	 * @param preselect		The field which should be preselected in the following link; [0]:the fieldname; [1]:the value
	 * @return	A HTML Form with a link in it.
	 */
	public static String getFastLinkPreselected( String formAction, String formName, String action, String label, String[] preselect ) {
		String ret = "";
		
		ret += 
			"	<div class=\"fastAction\">\n" +
			
			// "		<a href=\"" + formAction + action + "\" > <img src=\"skins/default/images/new_element.gif\" border=\"0\" onmouseover=\"myTip('" + label + "')\"\" /> </a>" + 
			// not so easy with a link because of preselected values...
			
			"		<form action=\"" + formAction + "\" method=\"post\" name=\"" + formName + "\">\n";
		
		if( preselect != null )
			ret +=
			"			<input type=\"hidden\" name=\""+ preselect[0] + "\" value=\"" + preselect[1] + "\"/>\n";
		
		ret +=
			"			<input type=\"hidden\" name=\"action\" value=\"" + action + "\"/>\n" +
			"			<a href=\"javascript:document." + formName + ".submit();\"><img src=\"skins/default/images/new_element.gif\" border=\"0\" onmouseover=\"myTip('" + label + "')\"\" /></a>\n" +
			"		</form>\n" +
			"	</div>\n";
		
		return ret;
	}
	


	private static String[] makeReachableURI;// [0]: DB; [1]: extern
	private static String contextRoot;

	

	/**
	 * Creates a HTML-list of elements. The label in a given language and its comment (also in the language) is returned.
	 * @param 	stringList	the URIs of the elements in a string separated by a comma
	 * @param	language	the language which should be presented.
	 * @return	A HTML-code containing linked elements of the given list.
	 */
	public static String getListOfElements( String stringList, String language ) {

		ArrayList<URI> list = new ArrayList<URI>();
		
		String[] strarray = stringList.split(",");
		for( int i = 0; i<strarray.length; i++ ){
			if( !strarray[ i ].equals("") )
				list.add( new URIImpl( strarray[i] ) );
			
			// System.out.println( strarray[i] + "want to add");
		}	
		
		return getListOfElements( list, language );
	}
	
	
	public int URICompare(URI a, URI b) {
		return (a.stringValue().compareTo(b.stringValue()));
	}
	
	
	/**
	 * Returns HTML-list of linked elements with onmouseover the comment
	 * @param list
	 * @param lang
	 * @return
	 */
	public static String getListOfElements2( ArrayList<URI> list, String lang ) {
		String ret = "";
		
		String label = "";
		String comment = "";
		
		if( list!=null && list.size()>0 ) {
			/*
			// model.dataContainer.AbstractElement cont = null;
			java.util.Collections.sort( list, new java.util.Comparator<URI>() {
				
				public int compare( URI a, URI b ) {
					
					return(a.stringValue().compareTo(b.stringValue()));
				}
	        } );
	        */
	
			java.util.Iterator<URI> it = list.iterator();
			while( it.hasNext() ) {
				
				URI uri = (URI)it.next();
				
				try {
					label = Mapper.selectLabel( uri, lang );
					// comment = Mapper.selectComment( uri, lang );
										
					ret += 
						"	<span onmouseover=\"more(this,'"+ getUriForHref(uri) +"')\" class=\"listLabel\" >" +
						controller.HelperFunctions.getLinkedLabel( uri, label ) + 
						"	</span>";
				} catch( Exception e ) {
					logger.error( "Exception in getListOfElements2:" + e );

				}
			}
		}
		
		return ret;
		
	}
	
	public static String getShortHTMLComment( String comment) {
		
		String ret = comment;
		final int SIZE = 100; 
		

		if( ret!=null ) {
			if( ret.length()>SIZE ) {
				ret = ret.trim().substring(0, SIZE - 3) + "...";
			}
		}
		else {
			ret = AbstractComponent.NOTHINGSELECTED;
		}
		
		return StringEscapeUtils.escapeHtml( ret ); 
	}
	
	
	/**
	 * Creates a HTML-list of elements. The label in a given language and its comment (also in the language) is returned.
	 * @param	list		the URIs of the elements, which should be presented.
	 * @param	language	the language which should be presented.
	 * @return	A HTML-code containing linked elements of the given list.
	 */
	public static String getListOfElements( ArrayList<URI> list, String lang ) {
		String ret = "";
		
		String label = "";
		String comment = "";
		// model.dataContainer.AbstractElement cont = null;
			
		if( list != null ) {
			java.util.Iterator<URI> it = list.iterator();
			while( it.hasNext() ) {
				
				URI uri = (URI)it.next();
				
				try {
					label = Mapper.selectLabel( uri, lang );
					comment = Mapper.selectComment( uri, lang );
					
					ret += getLinkedElementWithComment(uri, label, comment);
					
				} catch( Exception e ) {
					logger.error( "Exception in getListOfElements2:" + e );

				}
				
				
				
			}
		}
		
		return ret;
	}
	
	
	public static String getTagElementsHTML(String tag, URI type) {
		String ret = "";
		
		ArrayList<URI> list = AbstractDataConnector.selectTagElements(tag, type);
		
		ret = getListOfElements( list, Vocabulary.ENGLISH );
		
		return ret;
	}
	
	
	private static String getLinkedElementWithComment( URI uri, String label, String comment ) {
		String ret = "\n";
		
		ret += 
			"	<div class=\"listItem\">\n";
		
		ret += 
			"		<div class=\"listLabel\">\n" +
			controller.HelperFunctions.getLinkedLabel( uri, label ) + 
			"		</div>\n";

		ret += 
			"		<div class=\"listComment\">\n";
		
		int lenght = 100; // cut the comment after this lenght of characters
		String tmpComment = comment;
		if( tmpComment==null )
			tmpComment = AbstractComponent.NOTHINGSELECTED;
		else if( comment.length() > lenght )
			tmpComment = tmpComment.substring(0, lenght - 3) + "..."; // -3 because of 3 dots

		ret += StringEscapeUtils.escapeHtml( tmpComment );
		
		ret += 
			"		</div>\n";

		ret += 
			"	</div>\n";
		
		return ret;		
	}

	/**
	 * link a given string with its selfdescribing URL
	 * 
	 * @param	url		the href of the html-string and the name which is visible in the browser
	 * @return			the html-link
	 */
	public static String getLinkedURI( String url ) {
		
		return "<a href=\"" + url + "\" target=\"_blank\">" + url + "</a>";
	}
	
		
	/**
	 * link a given string with its selfdescribing URL
	 * 
	 * @param	url		the href of the html-string and the name which is visible in the browser
	 * @return			the html-link
	 */
	public static String getLinkedURI2( String url ) {
		String ret = getLinkedLabel2( url, url );
		
		return ret;
	}
	
	


	/**
	 * link a given label with an given url
	 * 
	 * @param	url		the href of the html-string
	 * @param	label	the name which is visible in the browser
	 * @param	classtag	the name of the HTML-class for stylesheet operations
	 * @return			the html-link
	 */
	public static String getLinkedChangeRequest( String url, String changeRequestId ) {
		String ret = "";
		
		if( url != null ){
			
			String url2 = makeReachableURI( url );
			
			ret += "<a href=\"show_changerequest.do?id=" + url2 + "&crid=" + changeRequestId + "\" >view</a>"; // no title tag, so that titles are translated by google-tabbar in browsers
		}
		
		return ret;					
	}
	
	public static String makeReachableURI( String url ) {

		String ret = "";
		
		if( url!=null ) {
			ret = url.replace( makeReachableURI[0], makeReachableURI[1] );
		}
		
		return ret;
	}
	
	/**
	 * 
	 * @param uri The uri of the element
	 * @return
	 */
	public static String getUriForHref( URI uri ) {
		
		if( uri!=null ) {
			return makeReachableURI( uri.stringValue() );
		}
		else
			return "";
		
	}
	
	
	public static String getCSSTypeByUri( URI uri ) {
		
		String ret = "";
		URI type = AbstractDataConnector.getType(uri);
		if( type!=null ) {
			if( type.equals(Vocabulary.CLASS) )
				ret = "ct";
			else if( type.equals(Vocabulary.DATATYPEPROPERTY) || type.equals(Vocabulary.OBJECTPROPERTY) )
				ret = "pt";
			else if( type.equals(Vocabulary.ONTOLOGYMODULE) )
				ret = "ot";
			else if( type.equals(Vocabulary.ARCHIVEDCLASS) )
				ret = "ct";
			else if( type.equals(Vocabulary.ARCHIVEDDATATYPEPROPERTY) || type.equals(Vocabulary.ARCHIVEDOBJECTPROPERTY) )
				ret = "pt";
			else if( type.equals(Vocabulary.ARCHIVEDONTOLOGYMODULE) )
				ret = "ot";
		}
		
		return ret;		
	}
	

	/**
	 * link a given label with an given url
	 * 
	 * @param	url		the href of the html-string
	 * @param	label	the name which is visible in the browser
	 * @param	classtag	the name of the HTML-class for stylesheet operations
	 * @return			the html-link
	 */
	public static String getLinkedLabel( URI uri, String label, String classtag, String comment ) {
		String ret = "";
		String url = uri.stringValue();
		
		
		if( label==null )
			ret = "";
		else if( url != null ){
			
			/*
			String csstype = getCSSTypeByUri( uri );
			if( !csstype.equals("") ) {
				if( classtag==null || classtag.trim().equals("") ) {
					classtag = csstype;
				}
				else {
					classtag = classtag.trim() + " " + csstype;
				}
			}
			*/
						
			if( classtag!=null && !classtag.trim().equals("") )
				classtag = " class=\"" + classtag + "\"";
			else
				classtag = "";
			
			String tmpTitle = "";	
			String onmouseover = "";
			if( comment!=null && !comment.equals("") ) {
				
				comment = HelperFunctions.getShortHTMLComment(comment);
				
				/*
				 * this requests the FlickrAPI and hence needs time...
				String flickrImage = "";
				
				try {
					ArrayList<String> flickrIds = Mapper.selectImages( uri );
					if( flickrIds!=null && flickrIds.size()>0 ) {	
						String flickrPhotoId = flickrIds.get( 0 );
					
						flickrImage = Images.getFlickrImage( flickrPhotoId );
					}
				}
				catch ( Exception e ) {}
				*/
				
				onmouseover = " onmouseover=\"myTip('" + StringEscapeUtils.escapeJavaScript( comment ) + "')\"";
					
				if( !classtag.equals(""))
					tmpTitle = " title=\"" + comment + "\"";
				else
					tmpTitle = "";				
			}
			
			String url2 = makeReachableURI( url );
	
			if( url.equals( label ) )
				label = url2;
			
			
			ret += "<a href=\"\" onclick=\"return changeLoc('" + url2 + "');\"" + classtag + tmpTitle + onmouseover + ">" + StringEscapeUtils.escapeHtml( label ) + "</a>"; // no title tag, so that titles are translated by google-tabbar in browsers
		}
		
		return ret;					
	}


	/**
	 * link a given label with an given url
	 * 
	 * @param	url		the href of the html-string
	 * @param	label	the name which is visible in the browser
	 * @param	classtag	the name of the HTML-class for stylesheet operations
	 * @return			the html-link
	 */
	public static String getLinkedLabel( URI uri, String label, String classtag ) {

		return getLinkedLabel( uri, label, classtag, null );		
	}
	
		
	/**
	 * link a given label with an given url
	 * 
	 * @param	url		the href of the html-string
	 * @param	label	the name which is visible in the browser
	 * @return			the html-link
	 */
	public static String getLinkedLabel2( String url, String label ) {
		String ret = "";
		
		if( url != null ){
					
			String url2 = makeReachableURI( url );
	
			if( url.equals( label ) )
				label = url2;
			
			ret += "<a href=\"" + url2 + "/\" onload=\"setWarning('"+url+"')\">" + org.apache.commons.lang.StringEscapeUtils.escapeHtml( label ) + "</a>";
		}
		
		return ret;		
	}
	
	
	/**
	 * link a given label with an given url
	 * 
	 * @param	url		the href of the html-string
	 * @param	label	the name which is visible in the browser
	 * @return			the html-link
	 */
	public static String getLinkedLabel( URI uri, String label ) {
		
		return getLinkedLabel( uri, label, null );		
	}
	

	public static String getLinkedLabelInLanguage( String url, String lang ) {
		return getLinkedLabelInLanguage(url, lang, null );
	}
	/**
	 * link a label which is stored to the URL with the URL
	 * @param url	The url of the html-link AND to which to find the label
	 * @return		the html-link or emtpy string ("") if there is no element for the url
	 */
	public static String getLinkedLabelInLanguage( String url, String lang, String classtag ) {
		String ret = "";
		
		if( url != null ){
			
			try {
				
				URI uri = new URIImpl( url );
				
				String label = Mapper.selectLabel( uri, lang );
		
				if( label!=null ) {

					String comment = Mapper.selectComment( uri, lang );
					
					if( comment==null )
						comment = AbstractComponent.NOTHINGSELECTED;
					
					ret += getLinkedLabel( uri, label, classtag, comment);
				}
			}
			catch( Exception e ) {
				// System.out.println( "getLinkedLabelInLanguage() " + e );
			}
		}
		
		return ret;		
	}
	
	
	public static String getNotificationHasToBelongToOM() {
		String note = "This element does not belong to any OntologyModule which seems not to be correct!";
		
		return getNotification( note );
	}
	
	public static String getNotification( String note ) {
		note = StringEscapeUtils.escapeHtml( note );
		note = note.replace( "\n", "<br />" );		
		return "<img style=\"cursor:help\" onmouseover=\"myTip('" + note + "');\" onclick=\"myTip('" + note + "');\" src=\"skins/default/images/help.png\" alt=\"note\" />";
	}

	
	public static String getWarning( String note ) {

		note = StringEscapeUtils.escapeHtml( note );
		note = note.replace( "\n", "<br />" );
		
		return "<img style=\"cursor:help\" onmouseover=\"myTip('" + note + "');\" onclick=\"myTip('" + note + "');\" src=\"skins/default/images/brick.png\" alt=\"warning\" />";
	}
	
	public static String getInformation( String note ) {
	
		// return "<img onclick=\"javacript:alert('" + note + "')\" src=\"skins/default/images/caution.gif\" title=\"" + note + "\" alt=\"\" />";		

		note = StringEscapeUtils.escapeHtml( note );
		note = note.replace( "\n", "<br />" );
		
		return "<img style=\"cursor:help\" onmouseover=\"myTip('" + note + "');\" onclick=\"myTip('" + note + "');\" src=\"skins/default/images/information.png\" alt=\"information\" />";
	}
	
	
	
	public static String getNotificationBrokenLink( String uri ) {
		String note = "This URL is not reachable";
		
		return "<img style=\"cursor:help\" onmouseover=\"setWarning('"+uri+"')\" src=\"\" name=\"warning\" title=\"" + note + "\" alt=\"broken link\" />";	
		//return "<img onload=\"setWarning('"+uri+"')\" onclick=\"javacript:alert('" + note + "')\" src=\"\" name=\"warning\" title=\"" + note + "\" alt=\"\" />";
	}

	public static void setMakeReachableURI(String[] makeReachableURI) {
		controller.HelperFunctions.makeReachableURI = makeReachableURI;
	}

	public static void SetContextRoot( String contextRoot ) {
		HelperFunctions.contextRoot = contextRoot;
	}
	public static String GetContextRoot() {
		return HelperFunctions.contextRoot;
	}
	

	/**
	 * Returns a tagcloud with links to the elements;
	 * @param elementType	specifies which elements should be shown. If null all elements are shown.
	 * @return	HTML-code containing a tagcloude (can be styled with stylesheet).
	 */
	public static String getTagCloude( List<RankedElement> list ) {	
		
		
		String ret = "";
		if (list==null)
			return ret;
		
		//int minfont = 6;
		//int maxfont = 26;
		double maxvalue = 0;
		double minvalue = 0;
		int countsizes = 5;
		
		
		
		java.util.Iterator<RankedElement> iter = list.iterator();
		while( iter.hasNext() ) {			
			double t = ((RankedElement)iter.next()).getValue();
			
			if( maxvalue < t )
				maxvalue = t;			
		}
		
		ret += "<div style=\"text-align:justify;\">\n";

		iter = list.iterator();
		String cloud = "";
		while( iter.hasNext() ) {
			
			RankedElement tmp = (RankedElement)iter.next();
			
			// int fontsize = minfont + new Double((double)tmp.getValue() / (double)maxvalue * maxfont).intValue();

			if( maxvalue < 1 ) // to protect from division by zero
				maxvalue = 1;
			Integer styleNr = (int)(tmp.getValue() * ( countsizes ) / ( maxvalue - minvalue ));
			
			String comment = tmp.getComment();
			if( comment!=null && comment.length() > 80 )
				comment = comment.substring(0, 77) + "...";
			
			cloud += HelperFunctions.getLinkedLabel( tmp.getUri(), tmp.getLabel(), "cloudfont" + styleNr.toString(), comment ) + "\n";
		}
		if( cloud.equals(""))
			ret += "No element selected yet.";
		else
			ret += cloud;
		
		ret += "</div>\n";
				

		
		return ret;		
	}

	
	public static String GetTabView( ArrayList<URI> list, String lang ) {
		String ret = "";
		
		
		
		return ret;		
	}
	
	
	
	public static String ShowImportantElements( String viewType, String lang ) {
		String ret = "";

//		ret += 
//			"	<div class=\"tabber\">\n";

		ArrayList<RankedElement> list = 
			controller.ElementRanker.GetImportantUris_alphabeticallySorted( viewType, 50, lang );
		
	
		
		//ret += 
		//	"		<div class=\"tabbertab\" title=\"Tagcloud\">";
		ret += HelperFunctions.getTagCloude( list );
		//ret += 
		//	"		</div>\n";
		
		/*
		ret += 
			"		<div class=\"tabbertab\" title=\"List\">";
		ret += HelperFunctions.getImportantElementList( list, lang);
		ret += 
			"		</div>\n";
		*/
		
		
		
//		ret += 
//			"		<div class=\"tabbertab\" title=\"Treeview\">";
//		ret += "not yet implemented...";
//		ret += "<br> It is unclear, which elements should be shown. If there are 1000 elements - should all these elements be shown? If not, how does the user get to know, that this are only the important ones?";
//		// ret += HelperFunctions.getImportantElementList( list, lang);
//		ret += 
//			"		</div>\n";	
		
		
		
		
//		ret += 
//			"	</div>\n";		
		
		return ret;
	}
	
	

	/**
	 * Creates a HTML-list of elements. The label in a given language and its comment (also in the language) is returned.
	 * @param	list		A sorted List of the ranked elements, which should be presented.
	 * @param	language	the language which should be presented.
	 * @return	A HTML-code containing linked elements of the given list.
	 */
	private static String getImportantElementList( ArrayList<RankedElement> list, String language ) {
		String ret = "";
		
		// model.dataContainer.AbstractElement cont = null;
		

		java.util.Iterator<RankedElement> iter = list.iterator();
		while( iter.hasNext() ) {

			RankedElement tmp = (RankedElement)iter.next();

			ret += getLinkedElementWithComment(tmp.getUri(), tmp.getLabel(), tmp.getComment() );
		}
		
		return ret; 
	}
	
	
	public static ArrayList<model.dataContainer.DataTypeContainer> getDatatypeArray() {
		ArrayList<model.dataContainer.DataTypeContainer> a = new ArrayList<model.dataContainer.DataTypeContainer>();
		
		try {
			a.add(new model.dataContainer.DataTypeContainer(Vocabulary.XMLSBOOLEAN, Mapper.selectLabel(Vocabulary.XMLSBOOLEAN, Vocabulary.ENGLISH)));
			a.add(new model.dataContainer.DataTypeContainer(Vocabulary.XMLSDATETIME, Mapper.selectLabel(Vocabulary.XMLSDATETIME, Vocabulary.ENGLISH)));
			a.add(new model.dataContainer.DataTypeContainer(Vocabulary.XMLSDOUBLE, Mapper.selectLabel(Vocabulary.XMLSDOUBLE, Vocabulary.ENGLISH)));
			a.add(new model.dataContainer.DataTypeContainer(Vocabulary.XMLSINTEGER, Mapper.selectLabel(Vocabulary.XMLSINTEGER, Vocabulary.ENGLISH)));
			a.add(new model.dataContainer.DataTypeContainer(Vocabulary.XMLSSTRING, Mapper.selectLabel(Vocabulary.XMLSSTRING, Vocabulary.ENGLISH)));
		} 
		catch ( Exception e ){
			
		}
		
		return a;
	}
	
	/*
	 * Returns a string which contains the date in Long representation
	 */
	public static String convertIntoString( long date ) {
		
		String ret = new Long( date ).toString();
		
		return ret;		
	}
	
	/**
	 * String has to be in Long representation (123123123123)
	 * @param date
	 * @return
	 */
	public static Date convertIntoDate( String date ) {
		
		GregorianCalendar cal = new GregorianCalendar();							
		cal.setTimeInMillis( new Long( date ) );
		
		Date ret = cal.getTime();
		
		return ret;		
	}
	
	

	
	public static String HTMLEncode(String s) {

		 char c[] = { '&', '\"', '\'', '�', '`', '<', '>', '�', '�', '�', '�', '�', '�', '�'};
		  String expansion[] = {"&amp;", "&quot;", "&apos;", "&quot;", "&quot;", "&lt;", "&gt;", "&#196;", "&#214;", "&#220;", "&#228;", "&#246;", "&#252;", "&#223;"};
		 
		 
	     StringBuffer st = new StringBuffer();
	     for (int i = 0; i < s.length(); i++) {
	    	 boolean copy = true;
	         char ch = s.charAt(i);
	         for (int j = 0; j < c.length ; j++) {
	        	 if (c[j]==ch) {
	        		 st.append(expansion[j]);
	        		 copy = false;
	        		 break;
	        	 }
	         }
	         if (copy) st.append(ch);
	     }
	     return st.toString().trim();
	 }

	
	
	
	
	
	public static String getWordNetText(String title) {
		String ret = "";
		String tmp = null;
		String command = AbstractComponent.getWordNetDirectory() + "wn " + title + " -over";
		
		BufferedReader in;
		
		try {
			Process p = Runtime.getRuntime().exec(command);
			in = new BufferedReader(new InputStreamReader(p.getInputStream()));
			while ((tmp = in.readLine()) != null) {
				ret += tmp + "<br/>\n";
			}
		} catch (Exception exc) { 
			
			logger.error(exc);
			return "";	
		}
		
		
		return HTMLEncode(ret).trim();		
	}
	
	
	

	public static ArrayList<String> extractStrings( String entry ) {
		return extractStrings( entry, DEFAULTPLITTER );
	}		
	public static ArrayList<String> extractStrings( String entry, String splitter ) {
		
		ArrayList<String> ret = null;

		String[] strarray = entry.split( splitter );
		
		for( int i = 0; i<strarray.length; i++ ){
			if( !strarray[i].equals("") ) {
				if( ret==null )
					ret = new ArrayList<String>();
				
				ret.add( strarray[i] );
			}
		}
		
		return ret;		
	}
	

	public static ArrayList<URI> extractURIs( String entry ) {
		return extractURIs( entry, DEFAULTPLITTER );
	}		
	public static ArrayList<URI> extractURIs( String entry, String splitter ) {
		
		ArrayList<URI> ret = null;

		if( entry!=null ) {
			String[] strarray = entry.split( splitter );
			
			for( int i = 0; i<strarray.length; i++ ){
				if( !strarray[i].equals("") ) {
					if( ret==null )
						ret = new ArrayList<URI>();
					
					/*
					if( strarray[i].indexOf("http://")!=0 ) {
						strarray[i] = makeReachableURI[0] + strarray[i];
					}
					ret.add( new URIImpl( strarray[i] ) );
					*/

					if( strarray[i].contains("http://") ) {
						ret.add( new URIImpl( strarray[i] ) );
					}
					else {					
						ret.add( AbstractDataConnector.getURI( strarray[i] ) );
					}
				}
			}
		}
		
		return ret;		
	}

	public static ArrayList<TranslationContainer> extractTranslations( String entry ) {
		
		ArrayList<TranslationContainer> ret = null;

		String[] strarray = entry.split( HelperFunctions.DEFAULTPLITTER );
		
		for( int i = 0; i<strarray.length; i++ ){
			if( !strarray[i].equals("") ) {
				if( ret==null )
					ret = new ArrayList<TranslationContainer>();
				
				ret.add( new TranslationContainer(strarray[i]) );
			}
		}
		
		return ret;		
	}
	
	
	
	

	
	/**
	 * concatinates all Translations separated with an "," - the language is separated with "; " from the value.
	 * @param uris
	 * @return
	 */
	public static String concatTranslations( ArrayList<TranslationContainer> list ) {
		String ret = "";
		
		if( list!=null ) {
			for (int i = 0; i<list.size(); i++) {
				ret += list.get(i).getValue() + HelperFunctions.INNERTRANSLATIONSPLITTER + list.get(i).getLanguage() + HelperFunctions.DEFAULTPLITTER;
			}
		}
		
		return ret.trim();
	}
	
	
	/**
	 * concatinates all Uris separated with an ","
	 * @param uris
	 * @return
	 */
	public static String concatURIs( ArrayList<URI> list ) {
		String ret = "";
		
		if( list!=null ) {
			for (int i = 0; i<list.size(); i++) {
				ret += getNiceURL( list.get(i) ) + HelperFunctions.DEFAULTPLITTER;
			}
		}
		
		return ret.trim();
	}
	public static String concatURIsReachable( ArrayList<URI> list ) {
		String ret = "";
		
		if( list!=null ) {
			for (int i = 0; i<list.size(); i++) {
				ret += getUriForHref( list.get(i) ) + HelperFunctions.DEFAULTPLITTER;
			}
		}
		
		return ret.trim();
	}
	
	
	
	/**
	 * concatinates all Strings separated with an ","
	 * @param uris
	 * @return
	 */
	public static String concatStrings( ArrayList<String> list, String splitter ) {
		String ret = "";
		
		if( list!=null ) {
			for (int i = 0; i<list.size(); i++) {
				ret += list.get(i) + splitter;
			}
		}
		
		return ret.trim();
	}
	

	/**
	 * concatinates all Strings separated with an ","
	 * @param uris
	 * @return
	 */
	public static String concatStrings( ArrayList<String> list ) {
		String ret = "";
		
		if( list!=null ) {
			for (int i = 0; i<list.size(); i++) {
				ret += list.get(i) + HelperFunctions.DEFAULTPLITTER;
			}
		}
		
		return ret.trim();
	}
	
	

	/**
	 * If url starts with [ or ends with ] these chars are removed.
	 * @param url
	 * @return
	 */
	private static String getNiceURL( URI uri ) {
		String ret = null;
				
		if( uri!= null )
			ret = uri.stringValue().replace("[", "").replace("]", "");
		
		return ret.trim();
	}
	
	

	/**
	 * Tries to get the details from the youtube API to the video with the id video_id
	 * @param video_id the id of the youtube-video
	 * @return
	 * @throws Exception
	 */
	public static org.w3c.dom.Document ParseYouTubeRESTget_details( String video_id ) throws Exception {

		String tmp ="http://www.youtube.com/api2_rest?method=youtube.videos.get_details&dev_id=" + YOUTUBEDEVID + "&video_id=" + java.net.URLEncoder.encode(video_id, "UTF-8");	
		
		java.net.URL url = new java.net.URL( tmp );
		
		javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
		javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
		
		return builder.parse( url.openStream() );
	}


	public static String getFieldNameInH3( model.Label field, boolean required, boolean plural ) {
		String ret = "";		

		ret = "<h3>";	
		ret += getFieldName(field, required, plural);
		ret += "</h3>\n";
		
		return ret;
	}
	
	public static String getFieldName( model.Label field, boolean required, boolean plural ) {

		String ret = "";		
		
		String name = "";	
		
		if( plural == true )
			name = field.getNamePlural();
		else
			name = field.getNameSingular();
		
		if( required == true ) {
			name = controller.HelperFunctions.getWarning( "This is a required field!" ) + name;
		}
		
		ret += name;
		
		if( !field.getSynonyms().equals( "" ) ) {
			ret +=
				" (" + field.getSynonyms() + ")";
		}
		
		if( !field.getComment().equals( "" ) ) {
			ret +=
				controller.HelperFunctions.getNotification( field.getComment() );
		}
		return ret;
	}
	
	/**
	 * Tries to build tree with root-nodes being a certain Concept in JSON or XML format
	 * @param language
	 * @return stringBuffer in JSON or XML format, description of nodes
	 */
	public static StringBuffer getConceptAsSuperNodeInTree(URI concept, boolean xml, String domain){
		StringBuffer ret = new StringBuffer();
		ArrayList<URI> list = null;
		boolean in_selected_domain = true;
		try{
			if (domain != null && !domain.equals("")){
				list = controller.elementMapper.OntologyModuleMapper.selectClassesBelongingToOM(new URIImpl(domain));
			}else list = null;
			if (list != null && !list.contains(concept))
				in_selected_domain = false;  //base concept not in domain
			
		}catch (Exception e){}
		
		if (xml == false)  //use json format
			ret.append("[");		
		if (xml == true)
			ret.append("<addnodestotree sublevel=\"true\""+ getParentList(concept, list) +">");
		
		if (xml == false){
			ret.append(constructNewTreeNodeJSON(concept, null, true, !in_selected_domain));
		}else{
			ret.append(constructNewTreeNodeXML(concept, null, true, !in_selected_domain));
		}
		
        if (xml == false){
        	ret.deleteCharAt(ret.length() - 1);
        	ret.append("\n]");
        }
		if (xml == true && !(ret.toString()).equals(""))
			ret.append("</addnodestotree>");		
		
		return ret;
	 }
	/**
	 * Tries to build root-nodes for tree-view in JSON or XML format
	 * @param language
	 * @return stringBuffer in JSON or XML format, description of root-nodes
	 */
	public static StringBuffer getSuperNodesForTree(boolean xml, boolean maximized, String language, String domain, int num, ArrayList<URI> nottoadd ){
		//ArrayList<RankedElement> list = controller.ElementRanker.GetImportantUris_alphabeticallySorted( model.RankedElement.VIEWTYPE_CLASS, Integer.MAX_VALUE, language);
		ArrayList<URI> list;// = controller.elementMapper.ClassMapper.selectAll();
		StringBuffer ret = new StringBuffer();
		StringBuffer ret_tolerance = new StringBuffer();
		int counter = 0, counter_exceed = 0;
		try{
			if (domain != null && !domain.equals("")){
				list = controller.elementMapper.OntologyModuleMapper.selectClassesBelongingToOM(new URIImpl(domain));
			}else{
				list = controller.elementMapper.ClassMapper.selectAll();
			}
		if (list == null) return new StringBuffer("");
		java.util.Iterator<URI> iter = list.iterator();
		rootloop: while( iter.hasNext() ) {
			//RankedElement tmp = (RankedElement)iter.next();
			URI tmp = (URI)iter.next();
			if (nottoadd!=null){
				if (nottoadd.contains(tmp)) continue rootloop;
			}
			//ArrayList<URI> tmplist = controller.elementMapper.ClassMapper.selectSubclassOf(tmp.getUri());
			ArrayList<URI> tmplist = controller.elementMapper.ClassMapper.selectSubclassOf(tmp);
			if (tmplist != null){
				tmplist.retainAll(list);  //evtl. delete nodes which are not in the domain
			}
			
    		if (tmplist == null || tmplist.size()==0){ // a superclass
				
				if (!(ret.toString()).equals("")){
					if (xml == false)
						ret.append("\n");
				}else{
					if (xml == true)
						ret.append("<addnodestotree>");
				}
				if (maximized){
					counter++;
					if (counter>num){
						counter_exceed++;
						if (counter_exceed > MAXPARALLELTREENODESTOLERANCE){
							if (xml == false){
								ret.append(constructNewTreeNodeMaximalReachedJSON());
								ret.deleteCharAt(ret.length() - 1);
							}
							else {  // this is normally never entered, but never mind...
								ret.append(constructNewTreeNodeMaximalReachedXML());
							}
							ret_tolerance = null;
							break rootloop;
						//return ret;
						}
					}
				}
				//construct JSON description of node
				if (xml == false){
					//ret.append(constructNewTreeNodeJSON(tmp.getUri()));
					if (counter <= num)
						ret.append(constructNewTreeNodeJSON(tmp, domain, false, false));
					else
						ret_tolerance.append(constructNewTreeNodeJSON(tmp, domain, false, false));
				}else{
					//ret.append(constructNewTreeNodeXML(tmp.getUri()));
					if (counter <= num)
						ret.append(constructNewTreeNodeXML(tmp, domain, false, false));
					else
						ret_tolerance.append(constructNewTreeNodeXML(tmp, domain, false, false));
				}
			}
		}//end while
		if (ret_tolerance != null && ret_tolerance.length() > 0)
			ret.append(ret_tolerance);
		if (xml == true && !(ret.toString()).equals(""))
			ret.append("</addnodestotree>");
		else if (xml == false){
			if (ret.charAt(ret.length()-1) == ',')
			ret.deleteCharAt(ret.length() - 1);
		}
		
		}catch (Exception e){e.printStackTrace();}
		
		return ret;		
	}	


	public static StringBuffer getSubNodesForTree(URI uri, boolean xml, boolean maximized, String domain, boolean inclass, int num, ArrayList<URI> nottoadd){
		StringBuffer ret = new StringBuffer();
		StringBuffer ret_tolerance = new StringBuffer();
		ArrayList<URI> classesofdomain = null;
		try {
			ArrayList<URI> concepts = controller.elementMapper.ClassMapper.selectAllClassesHavingClassInSubClassOf(uri);
			if (domain!=null && !domain.equals("") && concepts != null){
				classesofdomain = controller.elementMapper.OntologyModuleMapper.selectClassesBelongingToOM(new URIImpl(domain));
				if (classesofdomain == null){
					if (!inclass)
						concepts = null;
				}
				else{
					if (!inclass)
						concepts.retainAll(classesofdomain);
				}
			}
			if (nottoadd!=null){
				concepts.removeAll(nottoadd);
			}
			if (concepts == null || concepts.size()==0)
				return null;
			else {
				if (xml == false)  //use json format
					ret.append("[");
				else
					ret.append("<addnodestotree>");
			}

			Iterator<URI> i = concepts.iterator();
			int counter = 0, counter_exceed = 0;
			conceptloop: while (i.hasNext()) {
				String toAdd = "";
				if (maximized == true){
					counter++;
					if (counter>num){
						counter_exceed++;
						if (counter_exceed > MAXPARALLELTREENODESTOLERANCE){
							if (xml == false){
								toAdd += constructNewTreeNodeMaximalReachedJSON();
							}
							else {  // this is normally never entered, but never mind...
								toAdd += constructNewTreeNodeMaximalReachedXML();
							}
							ret.append(toAdd);
							ret_tolerance = null;
							break conceptloop;
						}
					}
				}
				
				URI concept = (URI) i.next();
				if (xml == false){
					if ( domain == null || domain.equals("") ||
						 ( classesofdomain != null && classesofdomain.contains(concept))){
						if (inclass)
							toAdd = constructNewTreeNodeJSON(concept, null, false, false);
						else
							toAdd = constructNewTreeNodeJSON(concept, domain, false, false);
					}
					else{
						if (inclass)
							toAdd = constructNewTreeNodeJSON(concept, null, false, true);
						else
							toAdd = constructNewTreeNodeJSON(concept, domain, false, true);
					}
						
				}
				else{
					if ( domain == null || domain.equals("") ||
							 ( classesofdomain != null && classesofdomain.contains(concept))){
						if (inclass)
							toAdd = constructNewTreeNodeXML(concept, null, false, false);
						else
							toAdd = constructNewTreeNodeXML(concept, domain, false, false);
					}
					else{
						if (inclass)
							toAdd = constructNewTreeNodeXML(concept, null, false, true);
						else
							toAdd = constructNewTreeNodeXML(concept, domain, false, true);
					}
				}
				if (counter_exceed == 0)
					ret.append(toAdd);
				else
					ret_tolerance.append(toAdd);
			}
		} catch (Exception e) {
			return null;
		}
		if (ret_tolerance != null && ret_tolerance.length() > 0)
			ret.append(ret_tolerance);
		// delete the last comma in JSON Format
        if (xml == false){
        	ret.deleteCharAt(ret.length() - 1);
        	ret.append("\n]");
        }else
        	ret.append("</addnodestotree>");
		
		return ret;
	}
	
	/**
	 * Checks whether for a given URI there exist sub-concepts or not
	 * @param uri URI to check if it is a father class
	 * @return 
	 */
	public static boolean isFolder(URI uri, String domain){
		boolean ret = false;
		try{
			ArrayList<URI> tmplist = controller.elementMapper.ClassMapper.selectAllClassesHavingClassInSubClassOf(uri);
			ArrayList<URI> omlist = null;

			if (domain != null && !domain.equals(""))
				omlist = controller.elementMapper.OntologyModuleMapper.selectClassesBelongingToOM(new URIImpl(domain));
			if (tmplist != null && ( omlist != null || domain == null || domain.equals(""))){
				if (omlist != null)
					tmplist.retainAll(omlist);
				if (tmplist != null && tmplist.size() > 0)
					ret = true;		
			}
		}catch (Exception e){} 
		return ret;
	}
	public static boolean isSubclassOf(URI concept, URI superconcept){
		boolean ret = false;
		try{
		ArrayList<URI> tmplist = controller.elementMapper.ClassMapper.selectAllClassesHavingClassInSubClassOf(superconcept);
		if (tmplist == null){
			/*ArrayList<URI> tmplist2 = controller.elementMapper.ClassMapper.selectSubclassOf(concept);
			if (tmplist2 == null)
				return true;
			else*/
				return false;
		}
		if (tmplist.contains(concept))
			return true;
		}catch (Exception e){}
		return ret;
	}
	public static String getParentsInXML(URI concept){
		String ret = "";
		if (!checkIsClass(concept))
			return ret;  //class does not exist -> no superconcepts
		try{
		ArrayList<URI> parentlist = controller.elementMapper.ClassMapper.selectSubclassOf(concept);
		if (parentlist == null){
			ret = "<dad>"+SUPERCONCEPTIDENTIFIER+"</dad>";
			return ret;  //class does exist and has no parents -> is superclass
		}
		Iterator<URI> it = parentlist.iterator();
		while (it.hasNext()){
			ret+="<dad>";
			URI tmp =(URI)it.next();
			ret+=getEncodedURI(getUriForHref(tmp));
			ret+="</dad>";
		}
		}catch(Exception e){}
		return ret;
	}
/*	public static StringBuffer getOntologyModulesJSON(String begin){
		StringBuffer ret = new StringBuffer();
		ArrayList<URI> omodules = controller.elementMapper.OntologyModuleMapper.selectAll();
		Iterator<URI> it = omodules.iterator();
		int counter = 0;
		String beginUpperCase = begin.toUpperCase();
		omsearch: while (it.hasNext()){
			URI omodule = (URI)it.next();
			String localNameUpperCase = omodule.getLocalName().toUpperCase();
			if (localNameUpperCase.startsWith(beginUpperCase))
			{
				counter++;
				if (counter > MAXONTMODULESFORTREE)
					break omsearch;				
				if (counter == 1)
					ret.append("{");
				ret.append("\""+omodule.stringValue()+"\":\""+omodule.getLocalName()+"\",");
			}

		}
		if (counter > 0){
			ret.deleteCharAt(ret.length()-1); //delete komma
			ret.append("}");
		}
		return ret;
	}*/
	public static boolean checkIsClass(URI uri){
		
		URI type = AbstractDataConnector.getType(uri);
		if (type==null) 
			return false;
		
		if (type.equals(model.Vocabulary.CLASS))
			return true;
		else
			return false;
	}
	/**
	 * Methods to construct new nodes in Tree
	 * @param tmp URI
	 * @return
	 */
	private static String constructNewTreeNodeJSON(URI tmp, String domain, boolean strong, boolean grey_italic){
		String ret = "{title:\"";
		try{		
		ret+="<a class=treeElement href="+getEncodedURI(getUriForHref(tmp))+" target=_self>";
		if (grey_italic){
			ret += "<span class=treeItemNotInDomain>";
		}
		if (strong) 
			ret += "<span class=treeItemHighlight>";
		
		ret+= controller.elementMapper.ClassMapper.selectLabel(tmp, null);

		if (strong)
			ret += "</span>";
		if (grey_italic)
			ret += "</span>";
		
		ret+="</a>";

		ret += "\"";
		//int length = getEncodedURI(getUriForHref(tmp)).length();
		ret += ",isFolder:" + isFolder(tmp, domain) + ",objectId:\""

		+ getEncodedURI(getUriForHref(tmp)) +"\"},"; // Changed by Andi: do not cut the last character as now it is no "/"
		}catch(Exception e){}		
		return ret;
	}	
	private static String constructNewTreeNodeXML(URI tmp, String domain, boolean strong, boolean grey_italic){
		String ret="<newnode>";
		try{
			ret	+= "<title strong=\""+strong+"\" grey_italic=\""+grey_italic+"\" href=\""+getEncodedURI(getUriForHref(tmp))+"\">";
			ret += controller.elementMapper.ClassMapper.selectLabel(tmp, null);				    	
	    	ret += "</title>";
	    	//int length = getEncodedURI(getUriForHref(tmp)).length();
	    	ret	+= "<isFolder>"+isFolder(tmp, domain)+"</isFolder>"
	    	+ "<objectId>"+getEncodedURI(getUriForHref(tmp))+"</objectId>" // Changed by Andi: do not cut the last character as now it is no "/"
	    		+"</newnode>";
			}catch(Exception e){}	    	
	   return ret;
	}
	private static String constructNewTreeNodeMaximalReachedJSON(){
		return "{title:\"...\",objectId:\""+HelperFunctions.MORECONCEPTSOBJECTID+"\",isFolder:false,actionsDisabled:['move','addChild']},";
	}
	private static String constructNewTreeNodeMaximalReachedXML(){
		return 	  "<newnode>"
		+ "<title strong=\"false\">...</title>"
		+ "<isFolder>false</isFolder>"
		+ "<objectId>"+HelperFunctions.MORECONCEPTSOBJECTID+"</objectId>"
		+"</newnode>";
	}
	private static String getParentList(URI concept, ArrayList<URI> list){
		String ret = "";		
		try{
			//ArrayList<URI> parentlist = controller.elementMapper.ClassMapper.selectAllClassesHavingClassInSubClassOf(concept);
			ArrayList<URI> parentlist = controller.elementMapper.ClassMapper.selectSubclassOf(concept);
			ArrayList<URI> parentlist_indomain = new ArrayList();
			parentlist_indomain.addAll(parentlist);
			if (list != null  && list.size() > 0)
				parentlist_indomain.retainAll(list);
			
			parentlist.removeAll(parentlist_indomain);
			if (parentlist_indomain != null && parentlist_indomain.size() > 0){
				ret += " parentsindomain=\"";
				ret += getParentListLabelsAndHrefs(parentlist_indomain);
				ret+="\"";
			}
			if (parentlist != null && parentlist.size() > 0){
				ret += " parents=\"";
				ret += getParentListLabelsAndHrefs(parentlist);
				ret+="\"";
			}			
		}catch (Exception e){}
		return ret;
	}
    private static String getParentListLabelsAndHrefs(ArrayList<URI> list) throws Exception{
    	String ret="";
		Iterator<URI> iter = list.iterator();
		while (iter.hasNext()){
			URI tmp = (URI)iter.next();
			//ret += tmp.getLocalName().toString().trim();
//			int length = getEncodedURI(getUriForHref(tmp)).length();
			ret+=getEncodedURI(getUriForHref(tmp)); // Changed by Andi: do not cut the last character as now it is no "/"
			ret+="|";
			ret+=controller.elementMapper.ClassMapper.selectLabel(tmp, null);
			if (iter.hasNext())
				ret+=";";
		}
		return ret;
    }
	public static String getEncodedURI( String uri ) throws Exception {
	
		/*
		 * THE URIs should be stored in the database as it is (it should not be a must to construct from a not valid uri a valid uri; the uris in the database should always be valid!)
		 * 
		 * compare AbstractDataConnector.getURI() - this method makes out of the label a valid URI
		
		String ret = "";
		
		// split the uri in its sections between the "/".
		// encode each section in UTF8
		// merge each section.
		String[] parts = uri.split("/");
		if( parts!=null ) {
			for( int i=0; i<parts.length; i++) {
				ret += URLEncoder.encode( parts[i], "UTF8" ) + "/";
			}
		}
		if( uri.contains("http://") )
			ret = "http://" + ret;
	
		
		return ret;	
		*/
		
		return uri;
	}
	
	public static String getViewType( URI type ) {
		
		String ret = null;
		
		if( type!=null ) {
			if( type.equals( Vocabulary.CLASS ))
				ret = DHTMLConstants.CLASS_VIEWTYPE;
			else if( type.equals( Vocabulary.DATATYPEPROPERTY ) || type.equals( Vocabulary.OBJECTPROPERTY ))
				ret = DHTMLConstants.PROPERTY_VIEWTYPE;
			else if( type.equals( Vocabulary.ONTOLOGYMODULE ))
				ret = DHTMLConstants.ONTOLOGY_VIEWTYPE;
		}
		
		return ret;
	}
	
	
	public static void updateClickHistory( URI type, URI uri, int actionCode, HttpSession session, Cookie cookies[], HttpServletResponse response ) {

		String viewtype = HelperFunctions.getViewType( type );
		
		//search for the cookie
		String cookieName = "clickhistory";
		Cookie myCookie = null;
		String cookieText = "";
		String SPLITTER = ",";

		if (cookies!=null) {
			for (int i = 0; i < cookies.length; i++) {
				if (cookies[i].getName().equals(cookieName))  {
					myCookie = cookies[i];
					break;
				}
			}
		}

		//if there is data stored in a cookie load it into the session-variable
		if (myCookie!=null) {
			String[] s = myCookie.getValue().split(SPLITTER);
			for (int i = 0; i < s.length; i++) {
				
				if( s[i]!=null && !s[i].trim().equals("") ) {
					
					URI tmp = new URIImpl( s[i] );
					// TODO: save in the cooky also the action, which was done with the element.
					session.setAttribute("clickhistory[" + i + "]", new ActionOnElement( tmp, getViewType( AbstractDataConnector.getType(tmp) ), ActionOnElement.ACTIONCODE_VIEWEN ) );
				}
			}
		}

		// Store the current visited element:
		if( uri != null ) {
			
			if(	viewtype!=null && (
					viewtype.equals( DHTMLConstants.CLASS_VIEWTYPE ) ||
					viewtype.equals( DHTMLConstants.PROPERTY_VIEWTYPE ) ||
					viewtype.equals( DHTMLConstants.ONTOLOGY_VIEWTYPE ) )
					) {
			
			
				int countClicks = 7;
				String actualUri = uri.stringValue();
				session.setMaxInactiveInterval( 360000 );
			
				if( session.getAttribute( "clickhistory[0]" ) == null ) {
					// if there is never stored an element:
					session.setAttribute( "clickhistory[0]", new ActionOnElement( uri, viewtype, actionCode ) );
				}
				else if( !((ActionOnElement)session.getAttribute( "clickhistory[0]" )).getUri().equals( uri ) ) {
					// if last != actual
					int count = countClicks - 1;
					// move the elements 1 elemement backwards:
					while( count >= 0 ) {
						
						ActionOnElement tmp = (ActionOnElement)session.getAttribute( "clickhistory[" + count + "]" );	
						
						if( tmp != null ) {						
							
							session.setAttribute( "clickhistory[" + (count+1) + "]", tmp );							
							cookieText = SPLITTER + tmp.getUri() + cookieText;
						}	
						count--;
					}
					session.setAttribute( "clickhistory[0]", new ActionOnElement( uri, viewtype, actionCode ) );
					cookieText = actualUri.concat(cookieText);
					
					Cookie cookie = new Cookie("clickhistory", cookieText);
					cookie.setMaxAge(60*60*24*7);
					cookie.setPath( GetContextRoot() );
					response.addCookie(cookie);
				}
			}

		}
	}
	

	public static String getFreezepointUriEnding( Calendar date ) {
		
		int year = date.get( Calendar.YEAR );
		int month = date.get( Calendar.MONTH ) + 1;
		int day = date.get( Calendar.DAY_OF_MONTH );
		int hour = date.get( Calendar.HOUR_OF_DAY );
		int min = date.get( Calendar.MINUTE );
		int sec = date.get( Calendar.SECOND );
		
		String ret = year + "-" + (month<10? "0"+month : month) + "-" + (day<10? "0"+day : day) + "_" + (hour<10? "0"+hour : hour) + "-" + (min<10? "0"+min : min) + "-" + (sec<10? "0"+sec : sec);
		
		return ret;
	}

}
